/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "纹理节点.h"
#include "节点数据声明.h"

#include "材质纹理JIT函数绑定.h"

#include "节点/节点树.h"

#include "../插座/字符插座.h"
#include "../插座/C_数值插座.h"
#include "../插座/list/list数值插座.h"
#include "../socket_utils.h"

#include "Context/数据创建销毁.h"
#include "Context/当前默认操作数据.h"

#include <core/shader_noise.h>

#include <UI/UI.h>
#include <ppl.h>


//#include <opencv2/tracking.hpp>
//#include <opencv2/core/ocl.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>




//#pragma comment(lib, "D:/DEV/OpenCV_SDK/lib/Debug/opencv_world430d.lib")
//#pragma comment(lib, "D:/DEV/OpenCV_SDK/lib/Debug/opencv_img_hash430d.lib")
//#pragma comment(lib, "D:/DEV/OpenCV_SDK/lib/Debug/ade.lib")



//static cv::Ptr<cv::Tracker> m_跟踪器 = 0;
//static std::map<C_流视频节点*, cv::Ptr<cv::Tracker>>		g_目标跟踪器;
static std::vector<cv::Ptr<cv::Tracker>>					g_目标跟踪器;
static std::map<C_流视频节点*, cv::MultiTracker>			g_多目标跟踪器;



C_纹理节点::C_纹理节点(S_设备环境& ctx) : C_节点基类("纹理节点") {
	m_Name = L"纹理";
	m_Ctx = ctx;
	C_插座基类* socket;
	DEF_创建图像插座_I(L"像素");
	
	DEF_创建纹理插座_O(L"纹理", ctx);
	
	//std::cout<<sizeof(E_节点类型)<<std::endl;
	m_纹理库 = f_alloc_StrIndexProp(S_光追后端::G纹理, L"");
	m_纹理库.m_私有 = true;
}

C_纹理节点::~C_纹理节点() {
	f_prop_Release(m_纹理库);
}

bool C_纹理节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	
	auto* outData = DEF_纹理插座数据(f_get输出插座(1), 0);

	if (socket1->f_isLink()) {
		auto& inData = *DEF_图像插座Value(socket1);
		if (inData.m_维度.x * inData.m_维度.y * inData.m_维度.z == 0) return false;

		f_ui_push纹理填充(outData, (uint8*)inData.m_像素.data(), inData.m_维度);
	}
	
	
	return false;
}

void C_纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_纹理库, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_纹理库, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_纹理节点(ctx);
}

C_节点基类* f_node_加载纹理节点(S_设备环境& ctx, FILE* f) {
	C_纹理节点* node = new C_纹理节点(ctx);
	return node;
}

void f_node_保存纹理节点(C_节点基类* n, FILE* f) {
	C_纹理节点* node = dynamic_cast<C_纹理节点*>(n);
}





C_外部纹理节点::C_外部纹理节点(S_设备环境& ctx) : C_节点基类(DEF_外部纹理节点, E_节点类型::e_节点Type_纹理) {
	m_Name = L"外部纹理";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建路径插座_I(L"路径");
	DEF_创建纹理插座_O(L"纹理", m_Ctx);

	m_Tex = f_scene_创建纹理(f_NodeCtx_get默认场景(), m_Ctx, m_Name);
	f_get输出插座(1)->f_setData(m_Tex);


	m_序列 = f_alloc_BoolProp(nullptr, L"序列");
	m_序列.m_私有 = true;
	f_prop_Bool(m_序列) = false;

	m_序列偏移 = f_alloc_I32Prop(nullptr, L"序列偏移");
	m_序列偏移.m_私有 = true;
	f_prop_I32(m_序列偏移) = 0;

	m_投影方式 = f_alloc_EnumProp(nullptr, { {L"平面", "平面"}, {L"方体", "立体线框"}, {L"球体", "球体"}, {L"圆柱", "圆柱"} }, L"序列偏移");
	m_投影方式.m_私有 = true;
	f_prop_enum(m_投影方式) = 0;



	f_构建代码_分配渲染器GPU属性变量(m_投影方式);
	m_Tex->m_纹理坐标计算类型 = m_投影方式.m_GPU缓存[0].m_Mem.m_偏移;

}

C_外部纹理节点::~C_外部纹理节点() {
	f_构建代码_释放渲染器GPU属性变量(m_投影方式);

	f_prop_Release(m_序列);
	f_prop_Release(m_序列偏移);

	f_tex_销毁纹理(m_Tex);
}

bool C_外部纹理节点::f_update() {
	auto& 路径 = *DEF_路径插座数据(f_get输入插座(1), 0);
	if (m_以加载文件记录 != 路径) {
		m_以加载文件记录 = 路径.string();

		auto* 纹理 = DEF_纹理插座数据(f_get输出插座(1), 0);
		//f_tex_加载图像文件(路径.string());
		f_scene_往渲染器里添加纹理({ m_以加载文件记录, 纹理, f_NodeCtx_get默认场景(), nullptr });
	}
	return false;
}

std::string C_外部纹理节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	
	auto& 路径 = *DEF_路径插座数据(f_get输入插座(1), 0);
	auto* 纹理 = DEF_纹理插座数据(f_get输出插座(1), 0);
	

	if (m_以加载文件记录 != 路径) {
		m_以加载文件记录 = 路径.string();

		std::string 拼接路径 = f_nodeCtx_相对路径补全(m_以加载文件记录);
		
		f_scene_往渲染器里添加纹理({ 拼接路径, 纹理, f_NodeCtx_get默认场景(), nullptr });
		//f_tex_从文件填充纹理(纹理, m_以加载文件记录, f_NodeCtx_get默认场景()->m_光追后端->m_渲染命令缓存);
		//f_tex_从文件填充纹理(纹理, m_以加载文件记录, S_绘图框架::g_资源加载管道);
		//f_scene_重载渲染器绑定纹理(纹理);
	}


	std::string name;
	
	auto rt = f_getThis节点树();
	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		name = f_str_汉字字符串转拼音(m_Name);
		//m_Code += "vec4 " + name + " = texture(Ts[nonuniformEXT(" + f_整数值转字符串(纹理->m_ID) + ")], );\n";
		//m_Code += "uint " + name + " = " + f_整数值转字符串(0) + ";\n";
		m_Code += "uint " + name + " = " + f_整数值转字符串(纹理->m_TexID) + ";\n";

		break;
	}
	case E_节点树类型::e_type_材质节点树: {
		name = f_getName();
		m_Code += "uint " + name + " = " + f_整数值转字符串(纹理->m_TexID) + ";\n";
		break;
	}
	default:
		break;
	}

	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_外部纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_7, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_序列, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_序列偏移, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
		}
		else if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_低版本号_7)) {
			下一次读取数据指针 = f_prop_Load(m_序列, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_序列偏移, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_外部纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_序列, 块);
	f_prop_Save(m_序列偏移, 块);
	f_prop_Save(m_投影方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建外部纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_外部纹理节点(ctx);
}

C_节点基类* f_node_加载外部纹理节点(S_设备环境& ctx, FILE* f) {
	C_外部纹理节点* node = new C_外部纹理节点(ctx);
	return node;
}

void f_node_保存外部纹理节点(C_节点基类* n, FILE* f) {
	C_外部纹理节点* node = dynamic_cast<C_外部纹理节点*>(n);
}






C_外部纹理集节点::C_外部纹理集节点(S_设备环境& ctx) : C_节点基类(DEF_外部纹理集节点, E_节点类型::e_节点Type_纹理) {
	m_Name = L"外部纹理集";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建路径插座_I(L"路径");
	DEF_创建纹理_1D插座_O(L"纹理", m_Ctx);

	//m_Tex = f_scene_创建纹理(f_NodeCtx_get默认场景(), m_Ctx, m_Name);
	//f_get输出插座(1)->f_setData(m_Tex);


	m_全部加载 = f_alloc_BoolProp(nullptr, L"全部加载");
	m_全部加载.m_私有 = true;
	f_prop_Bool(m_全部加载) = true;

	m_过滤名称 = f_alloc_StrProp(nullptr, L"名称");
	m_过滤名称.m_私有 = true;
	//f_prop_I32(m_序列偏移) = 0;

	m_投影方式 = f_alloc_EnumProp(nullptr, { {L"平面", "平面"}, {L"方体", "立体线框"}, {L"球体", "球体"}, {L"圆柱", "圆柱"} }, L"序列偏移");
	m_投影方式.m_私有 = true;
	f_prop_enum(m_投影方式) = 0;


	f_构建代码_分配渲染器GPU属性变量(m_投影方式);
	//m_Tex->m_纹理坐标计算类型 = m_投影方式.m_GPU缓存[0].m_Mem.m_偏移;
}

C_外部纹理集节点::~C_外部纹理集节点() {
	f_构建代码_释放渲染器GPU属性变量(m_投影方式);

	f_prop_Release(m_全部加载);
	f_prop_Release(m_过滤名称);
}

void C_外部纹理集节点::f_加载纹理() {
	auto& 路径 = *DEF_路径插座数据(f_get输入插座(1), 0);
	auto* 纹理 = DEF_纹理插座_1D数据(f_get输出插座(1), 0);


	if (m_以加载文件记录 != 路径) {
		m_以加载文件记录 = 路径.string();
		std::string 拼接路径 = f_nodeCtx_相对路径补全(m_以加载文件记录);


		S_目录文件包 目录文件;
		f_file_get目录下所有文件名(拼接路径, 目录文件, S_引擎配置::g_支持的图像格式);

		uint32 num = 目录文件.文件.size();
		
		f_node_创建纹理组(纹理, num, m_Ctx);
		for (uint32 i = 0; i < num; ++i) {
			auto 路径 = 拼接路径 + "/" + f_WStringToString(目录文件.文件[i]);
			f_scene_往渲染器里添加纹理({ 路径, 纹理->ptr_userData[i], f_NodeCtx_get默认场景(), nullptr });
		}
	}
}

bool C_外部纹理集节点::f_update() {
	auto& 路径 = *DEF_路径插座数据(f_get输入插座(1), 0);
	f_加载纹理();

	return false;
}

std::string C_外部纹理集节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";


	f_加载纹理();


	std::string name;

	auto rt = f_getThis节点树();
	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		name = f_str_汉字字符串转拼音(m_Name);
		//m_Code += "vec4 " + name + " = texture(Ts[nonuniformEXT(" + f_整数值转字符串(纹理->m_ID) + ")], );\n";
		//m_Code += "uint " + name + " = " + f_整数值转字符串(0) + ";\n";
		//m_Code += "uint " + name + " = " + f_整数值转字符串(纹理->m_TexID) + ";\n";

		break;
	}
	case E_节点树类型::e_type_材质节点树: {
		name = f_getName();
		//m_Code += "uint " + name + " = " + f_整数值转字符串(纹理->m_TexID) + ";\n";
		break;
	}
	default:
		break;
	}

	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_外部纹理集节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_6, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_全部加载, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_过滤名称, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_外部纹理集节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_全部加载, 块);
	f_prop_Save(m_过滤名称, 块);
	f_prop_Save(m_投影方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建外部纹理集节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_外部纹理集节点(ctx);
}

C_节点基类* f_node_加载外部纹理集节点(S_设备环境& ctx, FILE* f) {
	C_外部纹理集节点* node = new C_外部纹理集节点(ctx);
	return node;
}

void f_node_保存外部纹理集节点(C_节点基类* n, FILE* f) {
	C_外部纹理集节点* node = dynamic_cast<C_外部纹理集节点*>(n);
}




C_2D纹理采样节点::C_2D纹理采样节点(S_设备环境& ctx) : C_节点基类(DEF_2D纹理采样节点, E_节点类型::e_节点Type_纹理) {
	m_Name = L"纹理2D采样";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建纹理插座_I(L"纹理", ctx);
	DEF_创建Vec2插座_I(L"纹理坐标", nullptr);

	DEF_创建Vec4插座_O(L"颜色", ctx);


	(DEF_Vec2插座数据(f_get输入插座(2), 0)) = { 0,0 };


	m_投影方式 = f_alloc_EnumProp(nullptr, { {L"平面", "平面"}, {L"方体", "立体线框"}, {L"球体", "球体"}, {L"圆柱", "圆柱"} }, L"序列偏移");
	m_投影方式.m_私有 = true;
	f_prop_enum(m_投影方式) = 0;

}

C_2D纹理采样节点::~C_2D纹理采样节点() {
	f_prop_Release(m_投影方式);
}

bool C_2D纹理采样节点::f_update() {

	return false;
}

std::string C_2D纹理采样节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	std::string name = f_getName();

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);


	auto rt = f_getThis节点树();
	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		m_Code += "vec4 " + name + " = texture(Ts[nonuniformEXT(uint(" + socket1->f_getCode(0) + "))]," + socket2->f_getCode(0) + "); \n";

		break;
	}
	case E_节点树类型::e_type_材质节点树: {
		

		break;
	}
	default:
		break;
	}

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_2D纹理采样节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_2D纹理采样节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_投影方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建纹理采样节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_2D纹理采样节点(ctx);
}

C_节点基类* f_node_加载纹理采样节点(S_设备环境& ctx, FILE* f) {
	C_2D纹理采样节点* node = new C_2D纹理采样节点(ctx);
	return node;
}

void f_node_保存纹理采样节点(C_节点基类* n, FILE* f) {
	C_2D纹理采样节点* node = dynamic_cast<C_2D纹理采样节点*>(n);
}




void f_自动探测跟踪点(cv::Mat& 源图像, cv::Mat& 模板图像, std::vector<cv::Rect>& rect) {
	cv::Mat src;
	cv::Mat 目标图像;
	cv::matchTemplate(源图像, 模板图像, 目标图像, cv::TM_SQDIFF);
	cv::normalize(目标图像, 目标图像, 0, 255, cv::NORM_MINMAX);



	std::vector<float32> pro;  rect.clear();
	float64 mx = 0;  cv::Point loc, pre(-1, -1);


	uint32 num = 1;
	for (uint32 i = 0; i < num; ) {
		cv::minMaxLoc(目标图像, NULL, &mx, NULL, &loc);

		if (abs(loc.x - pre.x) > 10 && abs(loc.y - pre.y) > 10) {
			rect.push_back(cv::Rect(loc.x, loc.y, 模板图像.cols, 模板图像.rows));
			pre = loc;
			++i;
		}

		mx = 0;
		目标图像.at<float32>(loc.y, loc.x) = 0;
	}
	
}






/*static void f_Operator初始化跟踪点(S_结构对象指针 ops) {
	//C_节点面板* node = (C_节点面板*)ops;
	std::cout << "开始初始化跟踪点" << std::endl;
	C_流视频节点* 流视频节点 = ((C_流视频节点*)ops);

	if (流视频节点) {
		std::vector<S_Rect2Df> rects = 流视频节点->f_模板探测跟踪点({ 0, 10 }, { 0, 10 });

		if (rects.size()) {
			std::vector<S_RGBA8UI> color(rects.size(), { 50, 255, 50, 255 });
			f_ui_图像视口填充捕捉点(g当前视频视口->m_视频页面, rects, color);
		}
	}
}*/

cv::Ptr<cv::Tracker> f_create跟踪器类型(std::string type) {
	if (type == "CSRT") {
		return cv::TrackerCSRT::create();
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerCSRT::create());
	} else if (type == "KCF") {
		return cv::TrackerKCF::create();
	} else if (type == "MIL") {
		return cv::TrackerMIL::create();
	} else if (type == "MOSSE") {
		return cv::TrackerMOSSE::create();
	} else if (type == "GOTURN") {
		return cv::TrackerGOTURN::create();
	} else if (type == "TLD") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	} else if (type == "BOOSTING") {
		return cv::TrackerBoosting::create();
	} else if (type == "MEDIANFLOW") {
		return cv::TrackerMedianFlow::create();
	}

	return cv::TrackerTLD::create();
}











C_流视频节点::C_流视频节点(S_设备环境& ctx) : C_节点基类("流视频节点") {
	
	C_插座基类* socket;
	DEF_创建图像插座_I(L"像素");
	DEF_Rect32f_Array1D_插座创建_I(L"初始跟踪坐标")


	DEF_创建纹理插座_O(L"像素", ctx);
	DEF_Rect32f_Array1D_插座创建_O(L"跟踪坐标")


	g_多目标跟踪器[this] = cv::MultiTracker();
	f_set跟踪器类型("CSRT");

	m_帧 = (S_结构对象指针)new cv::Mat(512, 512, CV_8UC1);
	m_跟踪点数量 = 0;



	//m_Ops特效提取 = f_alloc_Ops(f_Operator初始化跟踪点, (S_结构对象指针)this);

	m_阈值步长 = 10;
	m_起始阈值 = 20;
	m_终止阈值 = 200;
	m_重复的最小次数 = 2;
	m_最小的斑点距离 = 10;

	m_斑点颜色限制 = true;
	m_斑点灰度 = 50;

	m_斑点面积限制 = true;
	m_斑点最小面积 = 25;
	m_斑点最大面积 = 5000;

	m_斑点面积限制 = true;
	m_斑点最小面积 = 4;
	m_斑点最大面积 = 1000;

	m_斑点圆度限制 = true;
	m_斑点最小圆度 = 0.8;
	m_斑点最大圆度 = 3.40282347e+38;

	m_斑点惯性率限制 = true;
	m_斑点最小惯性率 = 0.1;
	m_斑点最大惯性率 = 3.40282347e+38;

	m_斑点凸度限制 = true;
	m_斑点最小凸度 = 0.9;
	m_斑点最大凸度 = 3.40282347e+38;








	m_伽马 = 1.0;
	m_Prop伽马 = f_alloc_F32Prop(&m_伽马, L"伽马");
	
	m_亮度 = 0.0;
	m_Prop亮度 = f_alloc_F32Prop(&m_亮度, L"亮度");
	m_对比度 = 1.0;
	m_Prop对比度 = f_alloc_F32Prop(&m_对比度, L"对比度");

}

C_流视频节点::~C_流视频节点() {
	
}

bool C_流视频节点::f_update() {
	auto& inData = *DEF_图像插座Value(f_get输入插座(1));
	auto* outData = DEF_纹理插座数据(f_get输出插座(1), 0);

	auto* socketOut跟踪坐标 = f_get输出插座(2);
	auto& out跟踪坐标 = *DEF_Rect32f_Array1DValue(socketOut跟踪坐标, 0);

	


	if (inData.m_维度.x * inData.m_维度.y * inData.m_维度.z == 0) return false;
	

	/*auto* 初始跟踪坐标socket = f_get输入插座(2);
	if (初始跟踪坐标socket->f_isLink()) {
	}*/


	auto* p = inData.m_像素.data();


	//cv::VideoCapture capture;
	//cv::Mat img1(inData.m_维度.x, inData.m_维度.y, CV_8UC4);
	cv::Mat& frame = *((cv::Mat*)m_帧);
	//img1.create(inData.m_维度.x, inData.m_维度.y, CV_8UC4);
	frame.create(inData.m_维度.x, inData.m_维度.y, CV_8UC1);
	
	//cv::Mat img1(inData.m_维度.x, inData.m_维度.y, CV_8UC4);
	//Mat::isContinuous
	
	//cv::VideoWriter a;
	//capture>>img1;
	//img1.size[0] = inData.m_维度.x;
	//img1.size[1] = inData.m_维度.y;
	
	Concurrency::parallel_for<uint32>(0, inData.m_维度.y, [&](uint32 i){
		uint8* data = frame.ptr<uint8>(i);
		S_RGBA8UI* s = &(p[i * inData.m_维度.x]);

		for (uint32 j = 0; j < inData.m_维度.x; ++j) {
			//data[j] = cv::saturate_cast<uchar>(pow(s[j].r / 255.0, m_伽马) * 255.0);
			//saturate_cast <uchar>（pow（i / 255.0，gamma_） * 255.0）;
			/*s[j].r = cv::saturate_cast<uchar>(pow(s[j].r / 255.0, m_伽马) * 255.0);
			s[j].g = cv::saturate_cast<uchar>(pow(s[j].g / 255.0, m_伽马) * 255.0);
			s[j].b = cv::saturate_cast<uchar>(pow(s[j].b / 255.0, m_伽马) * 255.0);

			s[j].r = cv::saturate_cast<uchar>(s[j].r * m_对比度 + m_对比度);
			s[j].g = cv::saturate_cast<uchar>(s[j].g * m_对比度 + m_对比度);
			s[j].b = cv::saturate_cast<uchar>(s[j].b * m_对比度 + m_对比度);*/


			data[j] = s[j].r;
		}
	});


	f_ui_push纹理填充(outData, (uint8*)inData.m_像素.data(), inData.m_维度);






	cv::MultiTracker trackers;

	if (f_get输入插座(2)->m_有新数据) {
		

		std::vector<S_Rect2Df>& outCoord = *DEF_Rect32f_Array1DValue(f_get输入插座(2), 0);
		uint32 num = outCoord.size();

		//std::vector<cv::Rect> 初始跟踪区域;
		std::vector<cv::Rect2d> 初始跟踪区域(num);

		//static std::vector<cv::Ptr<cv::Tracker>> 跟踪算法;
		//跟踪算法.clear();
		g_目标跟踪器.resize(num);
		if (num) {
			m_跟踪点数量 = num;
			for (uint32 i = 0; i < num; ++i) {
			//for (auto& e : outCoord) {
				auto& e = outCoord[i];

				初始跟踪区域[i].x = e.offset.x;
				初始跟踪区域[i].y = e.offset.y;
				初始跟踪区域[i].width = e.extent.x;
				初始跟踪区域[i].height = e.extent.y;

				//跟踪算法.push_back(f_create跟踪器类型("CSRT"));

				g_目标跟踪器[i] = f_create跟踪器类型("CSRT");
				//g_目标跟踪器[i] = f_create跟踪器类型("MIL");
				if (i >= g_目标跟踪器.size()) {
					
					//g_目标跟踪器.push_back(f_create跟踪器类型("CSRT"));
					//g_目标跟踪器.push_back(f_create跟踪器类型("MOSSE"));
				}

				//m_跟踪器->init(frame, 初始跟踪区域[0]);
				g_目标跟踪器[i]->init(frame, 初始跟踪区域[i]);
			}

			
			//m_跟踪器->init(frame, 初始跟踪区域[0]);
			//cv::MultiTracker m;
			//m.add(f_create跟踪器类型("CSRT"), frame, cv::Rect2d());
			//g_多目标跟踪器[this].add(跟踪算法, frame, 初始跟踪区域);
		}
		//cv::selectROIs("rois", frame, 初始跟踪区域, false);
		return false;
	} else {
		
	}
	

	out跟踪坐标.resize(m_跟踪点数量);
	Concurrency::parallel_for<uint8>(0, m_跟踪点数量, [&](uint8 i){
		cv::Rect2d bbox;
		bool 追踪到 = g_目标跟踪器[i]->update(frame, bbox);
		if (追踪到) {
			out跟踪坐标[i].offset = { float32(bbox.x), float32(bbox.y) };
			out跟踪坐标[i].extent = { float32(bbox.width), float32(bbox.height) };

		} else {
			out跟踪坐标[i].offset = { 0, 0 };
			out跟踪坐标[i].extent = { 1, 1 };
		}
	});
	/*for (uint8 i = 0; i < m_跟踪点数量; ++i) {
		cv::Rect2d bbox;
		bool 追踪到 = g_目标跟踪器[i]->update(frame, bbox);
		if (追踪到) {
			out跟踪坐标[i].offset = { float32(bbox.x), float32(bbox.y) };
			out跟踪坐标[i].extent = { float32(bbox.width), float32(bbox.height) };

		} else {
			out跟踪坐标[i].offset = { 0, 0 };
			out跟踪坐标[i].extent = { 1, 1 };
		}
	}*/
	




	/*bool 跟踪到目标 = g_多目标跟踪器[this].update(frame);
	if (跟踪到目标) {
		for (auto j = 0; j < trackers.getObjects().size(); j++) {
			auto point = trackers.getObjects()[j];

			S_Rect2Df r;
			r.offset = {float32(point.x), float32(point.y)};
			r.extent = { float32(point.width), float32(point.height)};
			out跟踪坐标.push_back(r);
		}
	}*/


	return false;
	
}

void C_流视频节点::f_set跟踪器类型(std::string type) {
	if (type == "CSRT") {
		//m_跟踪器 = cv::TrackerCSRT::create();

		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerCSRT::create());
	}else if (type == "KCF") {
		
	} else if (type == "MIL") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	} else if (type == "MOSSE") {
		
	} else if (type == "GOTURN") {

	} else if (type == "TLD") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	} else if (type == "BOOSTING") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	} else if (type == "MEDIANFLOW") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	}
	
}


void C_流视频节点::f_init跟踪器坐标(const vec2& coord, const vec2& size) {
	cv::Rect2d bbox;
	//cv::Tracker* tracker = (cv::Tracker*)m_跟踪器;

	bbox.x = coord.x;
	bbox.y = coord.y;

	bbox.width = size.x;
	bbox.height = size.y;

	cv::Mat img1(512, 512, CV_8UC4);
	//tracker->init(img1, bbox);
}

std::vector<S_Rect2Df> C_流视频节点::f_模板探测跟踪点(const vec2& cols, const vec2& rows) {
	//*((cv::Mat*)m_初始帧) = ((cv::Mat*)m_帧)->clone();
	cv::Mat& 源图像		= (*((cv::Mat*)m_帧));
	
	auto& 初始跟踪坐标 = *DEF_Rect32f_Array1DValue(f_get输入插座(2), 0);
	初始跟踪坐标.clear();

	if (rows.y - rows.x <= 0 || cols.y - cols.x <= 0) {
		std::cout << "模板尺寸不符合" << std::endl;
		return 初始跟踪坐标;
	}
	if (源图像.cols <= cols.x - cols.y || 源图像.rows <= rows.x - rows.y) {
		std::cout<<"模板尺寸不符合"<<std::endl;
		return 初始跟踪坐标;
	}
	
	//cv::Mat 副本 = 源图像.clone();
	//cv::Mat& 模板图像 = 源图像(cv::Range(cols.x, cols.y), cv::Range(rows.x, rows.y));


	cv::SimpleBlobDetector::Params params;

	params.thresholdStep = m_阈值步长;
	params.minThreshold = m_起始阈值;
	params.maxThreshold = m_终止阈值;
	params.minRepeatability = m_重复的最小次数;
	params.minDistBetweenBlobs = m_最小的斑点距离;
	//params.filterByCircularity = true;
	//params.minCircularity = 0.5;
	params.filterByColor = m_斑点颜色限制;
	params.blobColor = m_斑点灰度;

	params.filterByArea = m_斑点面积限制;
	params.minArea = m_斑点最小面积;
	params.maxArea = m_斑点最大面积;

	params.filterByCircularity = m_斑点圆度限制;
	params.minCircularity = m_斑点最小圆度;
	params.maxCircularity = m_斑点最大圆度;

	params.filterByInertia = m_斑点惯性率限制;
	params.minInertiaRatio = m_斑点最小惯性率;
	params.maxInertiaRatio = m_斑点最大惯性率;

	params.filterByConvexity = m_斑点凸度限制;
	params.minConvexity = m_斑点最小凸度;
	params.maxConvexity = m_斑点最大凸度;

	cv::Ptr<cv::SimpleBlobDetector> 斑点检测器 = cv::SimpleBlobDetector::create(params);
	
	//cv::SimpleBlobDetector 斑点检测器;
	static std::vector<cv::KeyPoint> KeyPoint;
	
	斑点检测器->detect(源图像, KeyPoint);
	//斑点检测器->compute(副本, KeyPoint, 模板图像);
	std::cout << KeyPoint.size() << std::endl;
	
	
	std::vector<S_Rect2Df> 返回数据;
	for (auto& e : KeyPoint) {
		S_Rect2Df r;

		r.offset.x = e.pt.x;
		r.offset.y = e.pt.y;

		r.extent.x = e.size;
		r.extent.y = e.size;

		初始跟踪坐标.push_back(r);
		返回数据.push_back(r);
	}

	f_标记输出插座新数据(2, true, E_插座方向::e_插座Type_输入);
	//auto& out跟踪坐标 = *DEF_Rect32f_Array1DValue(socketOut跟踪坐标, 0);
	return 返回数据;





	

	/*std::vector<cv::Rect> rect;
	f_自动探测跟踪点(源图像, 模板图像, rect);
	std::cout<< rect.size() << std::endl;

	std::vector<S_Rect2Df>& outCoord = *DEF_Rect32f_Array1DValue(f_get输出插座(2), 0);

	outCoord.resize(rect.size());
	uint32 i=0;
	for (auto& e : rect) {
		outCoord[i].offset = {float32(e.x), float32(e.y)};
		outCoord[i].extent = { float32(e.width), float32(e.height)};
		
	}
	
	f_标记输出插座新数据(2, true, E_插座输出方向::e_插座Type_输出);*/
	
}

void C_流视频节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_阈值步长, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);



	fread(&m_阈值步长, sizeof(int32), 1, f);
	fread(&m_起始阈值, sizeof(int32), 1, f);
	fread(&m_终止阈值, sizeof(int32), 1, f);
	fread(&m_重复的最小次数, sizeof(int32), 1, f);
	fread(&m_最小的斑点距离, sizeof(int32), 1, f);
	fread(&m_斑点颜色限制, sizeof(bool), 1, f);
	fread(&m_斑点灰度, sizeof(uint8), 1, f);
	fread(&m_斑点面积限制, sizeof(bool), 1, f);
	fread(&m_斑点最小面积, sizeof(int32), 1, f);
	fread(&m_斑点最大面积, sizeof(int32), 1, f);
	fread(&m_斑点圆度限制, sizeof(bool), 1, f);
	fread(&m_斑点最小圆度, sizeof(float32), 1, f);
	fread(&m_斑点最大圆度, sizeof(float32), 1, f);
	fread(&m_斑点惯性率限制, sizeof(bool), 1, f);
	fread(&m_斑点最小惯性率, sizeof(float32), 1, f);
	fread(&m_斑点最大惯性率, sizeof(float32), 1, f);
	fread(&m_斑点凸度限制, sizeof(bool), 1, f);
	fread(&m_斑点最小凸度, sizeof(float32), 1, f);
	fread(&m_斑点最大凸度, sizeof(float32), 1, f);

}

void C_流视频节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);



	fwrite(&m_阈值步长, sizeof(int32), 1, f);
	fwrite(&m_起始阈值, sizeof(int32), 1, f);
	fwrite(&m_终止阈值, sizeof(int32), 1, f);
	fwrite(&m_重复的最小次数, sizeof(int32), 1, f);
	fwrite(&m_最小的斑点距离, sizeof(int32), 1, f);
	fwrite(&m_斑点颜色限制, sizeof(bool), 1, f);
	fwrite(&m_斑点灰度, sizeof(uint8), 1, f);
	fwrite(&m_斑点面积限制, sizeof(bool), 1, f);
	fwrite(&m_斑点最小面积, sizeof(int32), 1, f);
	fwrite(&m_斑点最大面积, sizeof(int32), 1, f);
	fwrite(&m_斑点圆度限制, sizeof(bool), 1, f);
	fwrite(&m_斑点最小圆度, sizeof(float32), 1, f);
	fwrite(&m_斑点最大圆度, sizeof(float32), 1, f);
	fwrite(&m_斑点惯性率限制, sizeof(bool), 1, f);
	fwrite(&m_斑点最小惯性率, sizeof(float32), 1, f);
	fwrite(&m_斑点最大惯性率, sizeof(float32), 1, f);
	fwrite(&m_斑点凸度限制, sizeof(bool), 1, f);
	fwrite(&m_斑点最小凸度, sizeof(float32), 1, f);
	fwrite(&m_斑点最大凸度, sizeof(float32), 1, f);

}











C_节点基类* f_node_加载流视频节点(S_设备环境& ctx, FILE* f) {
	C_流视频节点* node = new C_流视频节点(ctx);

	return node;
}

C_噪波纹理节点::C_噪波纹理节点(S_设备环境& ctx) : C_节点基类(DEF_噪波纹理节点) {
	m_Name = L"噪波";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec2_1D插座_I(L"偏移", nullptr);
	DEF_创建Vec2_1D插座_I(L"缩放", nullptr);
	DEF_创建F32_1D插座_I(L"亮度", nullptr);
	DEF_创建UI32插座_I(L"模式");
	
	DEF_创建F32_1D插座_O(L"x");
	DEF_创建F32_1D插座_O(L"y");
	DEF_创建F32_1D插座_O(L"z");


	(DEF_UI32插座数据(f_get输入插座(4), 0)) = 0;

	m_过程纹理属性 = f_alloc_纹理属性(nullptr, L"纹理属性");
	m_过程纹理属性.m_私有 = true;

	m_通道数量 = f_alloc_EnumProp(nullptr, { {L"a", ""}, {L"xy", ""}, {L"rgb", ""} }, L"通道");
	m_通道数量.m_私有 = true;

	m_偏移 = f_alloc_Vec2Prop(nullptr, L"偏移");
	m_偏移.m_私有 = true;

	m_缩放 = f_alloc_Vec2Prop(nullptr, L"缩放");
	m_缩放.m_私有 = true;

	m_强度 = f_alloc_F32Prop(nullptr, L"强度");
	m_强度.m_私有 = true;

	f_prop_Vec2(m_偏移) = {};
	f_prop_Vec2(m_缩放) = {1,1};
	f_prop_F32(m_强度) = 1;
}

C_噪波纹理节点::~C_噪波纹理节点() {
}

bool C_噪波纹理节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);
	auto* socket4 = f_get输入插座(4);

	auto& 偏移 = *DEF_Vec2插座_1D数据(f_get输入插座(1), 0);
	auto& 缩放 = *DEF_Vec2插座_1D数据(f_get输入插座(2), 0);
	auto& 亮度 = *DEF_F32插座_1D数据(f_get输入插座(3), 0);


	vec2* 偏移_ptr = &f_prop_Vec2(m_偏移);
	vec2* 缩放_ptr = &f_prop_Vec2(m_缩放);
	float32* 亮度_ptr = &f_prop_F32(m_强度);

	bool 单例[3] = { true, true, true };

	uint32 num = 1;
	if (f_get输入插座(1)->f_isLink()) {
		num = 偏移.count;
		偏移_ptr = 偏移.ptr_userData;
		单例[0] = false;
	}

	if (f_get输入插座(2)->f_isLink()) {
		缩放_ptr = 缩放.ptr_userData;
		if(缩放.count >= num) 单例[1] = false;

	}

	if (socket3->f_isLink()) {
		亮度_ptr = 亮度.ptr_userData;
		if (亮度.count >= num) 单例[2] = false;
	}

	
	uint32& 模式 = DEF_UI32插座数据(f_get输入插座(4), 0);

	S_F32Array* 噪波x = DEF_F32插座_1D数据(f_get输出插座(1), 0);
	S_F32Array* 噪波y = DEF_F32插座_1D数据(f_get输出插座(2), 0);
	S_F32Array* 噪波z = DEF_F32插座_1D数据(f_get输出插座(3), 0);

	f_JIT_1D噪波生成(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, 噪波x, 0);
	f_JIT_1D噪波生成(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, 噪波y, 124.3);
	f_JIT_1D噪波生成(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, 噪波z, 3578.137);
	


	if (单例[0]) {
		f_prop_TexProp(m_过程纹理属性)->m_TexCoordOffset = 偏移_ptr[0];
		f_prop_TexProp(m_过程纹理属性)->m_TexCoordScale = 缩放_ptr[0];
		f_prop_TexProp(m_过程纹理属性)->m_Intensity = 亮度_ptr[0];
		f_prop_TexProp(m_过程纹理属性)->m_TexColorMode = 模式;
		//float32 a = f_glsl_simplexNoise(偏移 * 缩放);
	}
	return false;
}

std::string C_噪波纹理节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto* rt = f_getThis节点树();

	//f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1);
	//f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 2);

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);
	auto* socket4 = f_get输入插座(4);

	std::string name_x = f_WStringToString(m_Name) + "_x";
	std::string name_y = f_WStringToString(m_Name) + "_y";
	std::string name_z = f_WStringToString(m_Name) + "_z";

	
	if (rt->m_树类型 == E_节点树类型::e_type_着色节点树) {

	}
	else {
		m_Code += "S_F32Array* " + name_x + ";\n";
		m_Code += "S_F32Array* " + name_y + ";\n";
		m_Code += "S_F32Array* " + name_z + ";\n";

		m_Code += "{\n";

		m_Code += socket1->f_构建变量代码(0);
		m_Code += socket2->f_构建变量代码(0);
		m_Code += socket3->f_构建变量代码(0);
		m_Code += socket4->f_构建变量代码(0);


		m_Code += "bool 单例[3] = { false, true, true };\n";

		m_Code += "uint32 num = " + f_代码构建_Array数组数量(socket1->f_getCode(0)) + ";\n";
		m_Code += "vec2* 偏移_ptr = " + socket1->f_getCode(0) + "->ptr_userData;\n";
		if (socket1->f_isLink() == false) {
			m_Code += "偏移_ptr = &(" + f_代码构建_属性变量(m_偏移, rt) + ");\n";
		}

		m_Code += "vec2* 缩放_ptr = " + socket2->f_getCode(0) + "->ptr_userData;\n";
		if (socket2->f_isLink() == false) {
			m_Code += "缩放_ptr = &(" + f_代码构建_属性变量(m_缩放, rt) + ");\n";
		}

		m_Code += "float32* 亮度_ptr = " + socket3->f_getCode(0) + "->ptr_userData;\n";
		if (socket3->f_isLink() == false) {
			m_Code += "亮度_ptr = &(" + f_代码构建_属性变量(m_强度, rt) + ");\n";
		}



		m_Code += "if(num > 0){\n";

		m_Code += "if(num <=" + f_代码构建_Array数组数量(socket2->f_getCode(0)) + "){\n";
		m_Code += "	单例[1] = false;\n";
		m_Code += "}\n";
		m_Code += "if(num <=" + f_代码构建_Array数组数量(socket3->f_getCode(0)) + "){\n";
		m_Code += "	单例[2] = false;\n";
		m_Code += "}\n";

		m_Code += "}\n";
		m_Code += "else {\n";

		m_Code += "单例[0] = true;\n";
		m_Code += "num = 1;\n";

		m_Code += "}\n";


		m_Code += name_x + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "num") + ";\n";
		m_Code += DEF_S(f_JIT_1D噪波生成);
		m_Code += "(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, " + name_x + ", 0);\n";

		m_Code += name_y + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "num") + ";\n";
		m_Code += DEF_S(f_JIT_1D噪波生成);
		m_Code += "(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, " + name_y + ", 124.3);\n";

		m_Code += name_z + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "num") + ";\n";
		m_Code += DEF_S(f_JIT_1D噪波生成);
		m_Code += "(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, " + name_z + ", 3578.137);\n";

		m_Code += m_ReleaseCode;
		m_Code += "}\n";
	}

	

	f_get输出插座(1)->f_setCode(name_x);
	f_get输出插座(2)->f_setCode(name_y);
	f_get输出插座(3)->f_setCode(name_z);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;

		m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name_x);
		m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name_y);
		m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name_z);
		return "";
	}
	else {
		释放 += f_代码构建_销毁数组(name_x);
		释放 += f_代码构建_销毁数组(name_y);
		释放 += f_代码构建_销毁数组(name_z);
	}
	return m_Code;
}

void C_噪波纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_过程纹理属性, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_通道数量, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_偏移, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_缩放, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_强度, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_噪波纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_过程纹理属性, 块);
	f_prop_Save(m_通道数量, 块);
	f_prop_Save(m_偏移, 块);
	f_prop_Save(m_缩放, 块);
	f_prop_Save(m_强度, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_噪波纹理节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);

	const C_噪波纹理节点* scr = dynamic_cast<const C_噪波纹理节点*>(node);
	f_prop_Vec2(m_偏移) = f_prop_Vec2(scr->m_偏移);
	f_prop_Vec2(m_缩放) = f_prop_Vec2(scr->m_缩放);
	f_prop_F32(m_强度) = f_prop_F32(scr->m_强度);
}

C_节点基类* f_node_创建噪波纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_噪波纹理节点(ctx);
}

C_节点基类* f_node_加载噪波纹理节点(S_设备环境& ctx, FILE* f) {
	C_噪波纹理节点* node = new C_噪波纹理节点(ctx);
	return node;
}

void f_node_保存噪波纹理节点(C_节点基类* n, FILE* f) {
	C_噪波纹理节点* node = dynamic_cast<C_噪波纹理节点*>(n);
}





C_渐变纹理节点::C_渐变纹理节点(S_设备环境& ctx) : C_节点基类(DEF_渐变纹理节点) {
	m_Name = L"渐变";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3插座_I(L"采样坐标", nullptr);
	DEF_创建F32插座_O(L"亮度", nullptr);

	m_类型 = f_alloc_EnumProp(nullptr, { {L"线性", ""}, {L"球", ""}, {L"径向", ""} }, L"通道");
	m_类型.m_私有 = true;


	f_构建代码_分配渲染器GPU属性变量(m_类型);
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(1));
}

C_渐变纹理节点::~C_渐变纹理节点() {
	f_prop_Release(m_类型);
}

bool C_渐变纹理节点::f_update() {

	return false;
}

std::string C_渐变纹理节点::DEF_节点编译函数{
	m_Code = "";
    m_ReleaseCode = "";

	auto* rt = f_getThis节点树();
	auto 类型 = f_代码构建_属性变量(m_类型, rt);
	auto name = f_getName();

	auto* socket1 = f_get输入插座(1);
	m_Code += socket1->f_构建变量代码(0);


	m_Code += "float " + name + " = f_texture_Gradient(" + socket1->f_getCode(0) + ", " + 类型 + ");\n";
	m_Code += m_ReleaseCode;

	f_get输出插座(1)->f_setCode(name);

	if (socket1->m_GPU缓存.m_Buf) {
		//((vec3*)socket1->m_GPU缓存->m_mappedPtr)[socket1->m_GPU内存偏移] = *DEF_Vec3插座数据(socket1, 0);
		f_buf_Vec3_at(socket1->m_GPU缓存) = DEF_Vec3插座数据(socket1);
	}
	f_buf_I32_at(m_类型.m_GPU缓存[0], 0) = f_prop_enum(m_类型);


	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;

		return "";
	}
	else {
		
	}
	return m_Code;
}

void C_渐变纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_渐变纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建渐变纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_渐变纹理节点(ctx);
}

C_节点基类* f_node_加载渐变纹理节点(S_设备环境& ctx, FILE* f) {
	C_渐变纹理节点* node = new C_渐变纹理节点(ctx);
	return node;
}

void f_node_保存渐变纹理节点(C_节点基类* n, FILE* f) {
	C_渐变纹理节点* node = dynamic_cast<C_渐变纹理节点*>(n);
}






C_纹理UV坐标节点::C_纹理UV坐标节点(S_设备环境& ctx) : C_节点基类(DEF_噪波纹理节点) {
	m_Name = L"UV";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建UI32插座_I(L"UV层", nullptr);

	DEF_创建Vec2插座_O(L"UV", nullptr);

}

C_纹理UV坐标节点::~C_纹理UV坐标节点() {
}

bool C_纹理UV坐标节点::f_update() {
	return false;
}

std::string C_纹理UV坐标节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	std::string name = f_getName();
	

	m_Code += "vec2 " + name + ";\n";

	auto* socket1 = f_get输入插座(1);
	m_Code += socket1->f_构建变量代码(0);

	std::string UV层 = socket1->f_getCode(0);
	m_Code += "if(" + UV层 + " < gGeom[callSceneData.InstanceIndex].uvLayerNum){\n";
	m_Code += "uvec3 uvIndex = uv_index.I[callSceneData.PrimitiveIndex + "+ UV层 + " * callSceneData.uvLayerOffset];\n";
	m_Code += "vec2 uv1 = uv_index.UV[uvIndex.x];\n";
	m_Code += "vec2 uv2 = uv_index.UV[uvIndex.y];\n";
	m_Code += "vec2 uv3 = uv_index.UV[uvIndex.z];\n";
	m_Code += name + " = uv1 * barycentrics.x + uv2.texCoord * barycentrics.y + uv3.texCoord * barycentrics.z;\n";
	m_Code += "} else {\n";
	m_Code += name + " = uv;\n";
	m_Code += "}\n";

	m_Code += m_ReleaseCode;



	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	else {
		//释放 += f_代码构建_销毁_Array(name);
	}
	return m_Code;
}

void C_纹理UV坐标节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_纹理UV坐标节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建纹理UV坐标节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_纹理UV坐标节点(ctx);
}

C_节点基类* f_node_加载纹理UV坐标节点(S_设备环境& ctx, FILE* f) {
	C_纹理UV坐标节点* node = new C_纹理UV坐标节点(ctx);
	return node;
}

void f_node_保存纹理UV坐标节点(C_节点基类* n, FILE* f) {
	C_纹理UV坐标节点* node = dynamic_cast<C_纹理UV坐标节点*>(n);
}



C_字符纹理节点::C_字符纹理节点(S_设备环境& ctx) : C_节点基类(DEF_棋盘格纹理节点) {
	m_Name = L"外部纹理";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建路径插座_I(L"路径");
	DEF_创建I32插座_I(L"字体大小");
	DEF_创建Vec4_1D插座_O(L"纹理坐标");

	m_字体文件 = f_alloc_PathProp(nullptr, L"字体文件");
}

C_字符纹理节点::~C_字符纹理节点() {
}

bool C_字符纹理节点::f_update() {
	return false;
}

std::string C_字符纹理节点::DEF_节点编译函数 {
	return "";
}

void C_字符纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_字符纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建字符纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_字符纹理节点(ctx);
}

C_节点基类* f_node_加载字符纹理节点(S_设备环境& ctx, FILE* f) {
	C_字符纹理节点* node = new C_字符纹理节点(ctx);
	return node;
}

void f_node_保存字符纹理节点(C_节点基类* n, FILE* f) {
	C_字符纹理节点* node = dynamic_cast<C_字符纹理节点*>(n);
}




C_棋盘格纹理节点::C_棋盘格纹理节点(S_设备环境& ctx) : C_节点基类(DEF_棋盘格纹理节点) {
	m_Name = L"棋盘格纹理";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3插座_I(L"采样坐标", nullptr);
	DEF_创建Vec3插座_I(L"大小", nullptr);

	DEF_创建F32插座_O(L"值", nullptr);

	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(1));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(2));

}

C_棋盘格纹理节点::~C_棋盘格纹理节点() {

}

bool C_棋盘格纹理节点::f_update() {
	return false;
}

std::string C_棋盘格纹理节点::DEF_节点编译函数{
	m_Code = "";
    m_ReleaseCode = "";

	auto* rt = f_getThis节点树();
	auto name = f_getName();

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	switch (rt->m_树类型)
	{
	case E_节点树类型::e_type_着色节点树: {
		m_Code += "float " + name + " = f_texture_Checker(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ");\n";

		if (socket1->f_isLink() == false && socket1->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(socket1->m_GPU缓存) = DEF_Vec3插座数据(socket1);
		}
		if (socket2->f_isLink() == false && socket2->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(socket2->m_GPU缓存) = DEF_Vec3插座数据(socket2);
		}

		break;
	}
	default:
		break;
	}
	
	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_棋盘格纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_棋盘格纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建棋盘格纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_棋盘格纹理节点(ctx);
}

C_节点基类* f_node_加载棋盘格纹理节点(S_设备环境& ctx, FILE* f) {
	C_棋盘格纹理节点* node = new C_棋盘格纹理节点(ctx);
	return node;
}

void f_node_保存棋盘格纹理节点(C_节点基类* n, FILE* f) {
	C_棋盘格纹理节点* node = dynamic_cast<C_棋盘格纹理节点*>(n);
}

